﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace AlgorithmTest
{
    // T_[四个数字排序]_[算法名]
    public class T_0106_MatrixReshape : IAlgorithm
    {
        // 566. 重塑矩阵

        // 在 MATLAB 中，有一个非常有用的函数 reshape ，它可以将一个 m x n 矩阵重塑为另一个大小不同（r x c）的新矩阵，但保留其原始数据。
        // 给你一个由二维数组 mat 表示的 m x n 矩阵，以及两个正整数 r 和 c ，分别表示想要的重构的矩阵的行数和列数。
        // 重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
        // 如果具有给定参数的 reshape 操作是可行且合理的，则输出新的重塑矩阵；否则，输出原始矩阵。

        // 提示：
        //  m == mat.length
        //  n == mat[i].length
        //  1 <= m, n <= 100
        //  -1000 <= mat[i][j] <= 1000
        //  1 <= r, c <= 300

        public void Test()
        {
            // 算法参数定义
            var mat = new int[][] { new int[] { 1, 2 }, new int[] { 3, 4 } };
            int r = 4, c = 2;
            // 算法执行与打印
            var res = MatrixReshape(mat, r, c);
            foreach (var item in res)
            {
                foreach (var iitem in item)
                {
                    Console.Write(iitem + " ");
                }
                Console.WriteLine();
            }
        }

        // 算法
        public int[][] MatrixReshape(int[][] mat, int r, int c)
        {
            int m = mat.Length, n = mat[0].Length;
            if (m * n != r * c)
                return mat;
            var res = new int[r][];
            for (int i = 0; i < r; i++)
            {
                res[i] = new int[c];
                for (int j = 0; j < c; j++)
                {
                    // 对应原矩阵的行索引
                    var matRi = (i * c + j) / n;
                    // 对应原矩阵的列索引
                    var matCj = (i * c + j) % n;
                    res[i][j] = mat[matRi][matCj];
                }
            }
            return res;
        }

        public int[,] MatrixReshape(int[,] mat, int r, int c)
        {
            // 获取第一行的长度
            var n = mat.GetLength(0);
            // mat.Length二维数组的元素总数==m*n
            if (mat.Length != r * c)
                return mat;
            var res = new int[r, c];
            for (int x = 0; x < mat.Length; ++x)
                res[x / c, x % c] = mat[x / n, x % n];
            return res;
        }
    }
}
